package com.neusoft.elmboot.service.impl;

import java.math.BigDecimal;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.neusoft.elmboot.constants.EditableProperties;
import com.neusoft.elmboot.constants.TransactionStatus;
import com.neusoft.elmboot.constants.TransactionType;
import com.neusoft.elmboot.mapper.VirtualWalletMapper;
import com.neusoft.elmboot.mapper.VirtualWalletTransactionMapper;
import com.neusoft.elmboot.po.InsufficientBalanceException;
import com.neusoft.elmboot.po.InvalidAmountException;
import com.neusoft.elmboot.po.VirtualWallet;
import com.neusoft.elmboot.po.VirtualWalletTransaction;
import com.neusoft.elmboot.service.VirtualWalletService;

/**
 * @author chj
 * @date 2024年10月20日
 */
@Service
public class VirtualWalletServiceImpl implements VirtualWalletService {

	@Autowired
	private VirtualWalletMapper virtualWalletMapper;

	@Autowired
	private VirtualWalletTransactionMapper virtualWalletTransactionMapper;

	@Override
	public int saveVirtualWallet(Long walletId) {
		// TODO Auto-generated method stub
		VirtualWallet wallet = new VirtualWallet(walletId);
		return virtualWalletMapper.saveVirtualWallet(wallet);
	}

	@Override
	@Transactional
	public int debit(Long walletId, BigDecimal amount) {
		// TODO Auto-generated method stub
		VirtualWallet wallet = virtualWalletMapper.getVirtualWallet(walletId);

		VirtualWalletTransaction transaction = new VirtualWalletTransaction(System.currentTimeMillis(), amount,
				walletId, walletId, TransactionType.DEBIT, TransactionStatus.TO_BE_EXECUTED);

		virtualWalletTransactionMapper.saveTransaction(transaction);
		Long transactionId = virtualWalletTransactionMapper.getNewIds();

		try {
			wallet.debit(amount.add(amount.multiply(EditableProperties.SURCHARGE)));
			virtualWalletMapper.updateBalance(walletId, wallet.balance());
			return virtualWalletTransactionMapper.updateStatus(transactionId, TransactionStatus.EXECUTED);
		} catch (InsufficientBalanceException e) {
			// TODO Auto-generated catch block
			virtualWalletTransactionMapper.updateStatus(transactionId, TransactionStatus.FAILED);
			e.printStackTrace();
		} catch (InvalidAmountException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return 0;

	}

	@Override
	@Transactional
	public int credit(Long walletId, BigDecimal amount) {
		// TODO Auto-generated method stub
		VirtualWallet wallet = virtualWalletMapper.getVirtualWallet(walletId);

		VirtualWalletTransaction transaction = new VirtualWalletTransaction(System.currentTimeMillis(), amount,
				walletId, walletId, TransactionType.CREDIT, TransactionStatus.TO_BE_EXECUTED);

		virtualWalletTransactionMapper.saveTransaction(transaction);
		Long transactionId = virtualWalletTransactionMapper.getNewIds();
		try {
			wallet.credit(amount.add(amount.multiply(EditableProperties.REFILLBONUS)));
			virtualWalletMapper.updateBalance(walletId, wallet.balance());
			return virtualWalletTransactionMapper.updateStatus(transactionId, TransactionStatus.EXECUTED);
		} catch (InvalidAmountException e) {
			// TODO Auto-generated catch block
			virtualWalletTransactionMapper.updateStatus(transactionId, TransactionStatus.FAILED);
			e.printStackTrace();
		}
		return 0;

	}

	@Override
	@Transactional
	public int transfer(Long fromWalletId, Long toWalletId, BigDecimal amount) {
		// TODO Auto-generated method stub
		VirtualWallet fromWallet = virtualWalletMapper.getVirtualWallet(fromWalletId);
		VirtualWallet toWallet = virtualWalletMapper.getVirtualWallet(toWalletId);

		VirtualWalletTransaction transaction = new VirtualWalletTransaction(System.currentTimeMillis(), amount,
				fromWalletId, toWalletId, TransactionType.TRANSFER, TransactionStatus.TO_BE_EXECUTED);

		virtualWalletTransactionMapper.saveTransaction(transaction);
		Long transactionId = virtualWalletTransactionMapper.getNewIds();

		try {
			fromWallet.debit(amount);
			virtualWalletMapper.updateBalance(fromWalletId, fromWallet.balance());
		} catch (InsufficientBalanceException e) {
			// TODO Auto-generated catch block
			virtualWalletTransactionMapper.updateStatus(transactionId, TransactionStatus.CLOSED);
			e.printStackTrace();
		} catch (InvalidAmountException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			toWallet.credit(amount);
			virtualWalletMapper.updateBalance(toWalletId, toWallet.balance());
			return virtualWalletTransactionMapper.updateStatus(transactionId, TransactionStatus.EXECUTED);
		} catch (InvalidAmountException e) {
			// TODO Auto-generated catch block
			virtualWalletTransactionMapper.updateStatus(transactionId, TransactionStatus.FAILED);
			e.printStackTrace();
		}
		return 0;
	}

	@Override
	public VirtualWallet getVirtualWallet(Long walletId) {
		// TODO Auto-generated method stub
		VirtualWallet wallet = virtualWalletMapper.getVirtualWallet(walletId);
		wallet.setTransactionList(virtualWalletTransactionMapper.listTransactions(walletId));
		return wallet;
	}

	@Override
	public BigDecimal getBalance(Long walletId) {
		// TODO Auto-generated method stub
		VirtualWallet wallet = virtualWalletMapper.getVirtualWallet(walletId);
		return wallet.balance();
	}

	@Override
	public List<VirtualWalletTransaction> listTransactions(Long walletId) {

		// TODO Auto-generated method stub
		return virtualWalletTransactionMapper.listTransactions(walletId);
	}

	@Override
	public int closeVIP(Long walletId) {
		// TODO Auto-generated method stub
		VirtualWallet wallet = virtualWalletMapper.getVirtualWallet(walletId);
		try {
			wallet.closeVIP();
			return virtualWalletMapper.updateIsVIP(walletId, wallet.isVIP());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return 0;

	}

	@Override
	public int openVIP(Long walletId) {
		// TODO Auto-generated method stub
		VirtualWallet wallet = virtualWalletMapper.getVirtualWallet(walletId);
		try {
			wallet.openVIP();
			return virtualWalletMapper.updateIsVIP(walletId, wallet.isVIP());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return 0;

	}

	@Override
	public int frozen(Long walletId, BigDecimal frozenAmount) {
		// TODO Auto-generated method stub
		VirtualWallet wallet = virtualWalletMapper.getVirtualWallet(walletId);
		try {
			wallet.frozen(frozenAmount);
			return virtualWalletMapper.updateFrozenAmount(walletId, wallet.frozenAmount());
		} catch (InvalidAmountException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InsufficientBalanceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return 0;

	}

	@Override
	public int unfrozen(Long walletId, BigDecimal frozenAmount) {
		// TODO Auto-generated method stub
		VirtualWallet wallet = virtualWalletMapper.getVirtualWallet(walletId);
		try {
			wallet.unfrozen(frozenAmount);
			return virtualWalletMapper.updateFrozenAmount(walletId, wallet.frozenAmount());
		} catch (InvalidAmountException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InsufficientBalanceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return 0;

	}

	@Override
	public int increaseOverdraftAmount(Long walletId, BigDecimal amount) {
		// TODO Auto-generated method stub
		VirtualWallet wallet = virtualWalletMapper.getVirtualWallet(walletId);
		try {
			wallet.increaseOverdraftAmount(amount);
			return virtualWalletMapper.updateOverdraftAmount(walletId, wallet.overdraftAmount());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return 0;
	}

	@Override
	public int decreaseOverdraftAmount(Long walletId, BigDecimal amount) {
		// TODO Auto-generated method stub
		VirtualWallet wallet = virtualWalletMapper.getVirtualWallet(walletId);
		try {
			wallet.decreaseOverdraftAmount(amount);
			return virtualWalletMapper.updateOverdraftAmount(walletId, wallet.overdraftAmount());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return 0;
	}

	@Override
	public int closeOverdraft(Long walletId) {
		// TODO Auto-generated method stub
		VirtualWallet wallet = virtualWalletMapper.getVirtualWallet(walletId);
		try {
			wallet.closeOverdraft();
			return virtualWalletMapper.updateIsAllowedOverdraft(walletId, wallet.isAllowedOverdraft());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return 0;

	}

	@Override
	public int openOverdraft(Long walletId) {
		// TODO Auto-generated method stub
		VirtualWallet wallet = virtualWalletMapper.getVirtualWallet(walletId);
		try {
			wallet.openOverdraft();
			return virtualWalletMapper.updateIsAllowedOverdraft(walletId, wallet.isAllowedOverdraft());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return 0;

	}

}
